package com.apes.fn.scm.settleCheck.service;

import com.alibaba.fastjson.JSONObject;
import com.apes.fn.business.insurance.modle.PolicyInformation;
import com.apes.fn.business.insurance.modle.PolicyInformationItem;
import com.apes.fn.business.insurance.repository.PolicyInformationRepository;
import com.apes.fn.scm.advancePayment.AdvancePayment;
import com.apes.fn.scm.advancePayment.AdvancePaymentMethod;
import com.apes.fn.scm.advancePayment.AdvancePaymentRepository;
import com.apes.fn.scm.merchant.settlement.service.MerchantSettlementService;
import com.apes.fn.scm.retailOrder.model.RetailOrder;
import com.apes.fn.scm.retailOrder.model.RetailOrderItem;
import com.apes.fn.scm.retailOrder.model.RetailOrderPayMethod;
import com.apes.fn.scm.retailOrder.repository.RetailOrderRepository;
import com.apes.fn.scm.retailReturn.RetailReturn;
import com.apes.fn.scm.retailReturn.RetailReturnRepository;
import com.apes.fn.scm.settleCheck.model.PartnerCheck;
import com.apes.fn.scm.settleCheck.model.PartnerCheckCreate;
import com.apes.fn.scm.settleCheck.model.PartnerCheckItem;
import com.apes.fn.scm.settleCheck.reponsitory.PartnerCheckRepository;
import com.apes.fn.scm.used.model.UsedCar;
import com.apes.fn.scm.used.repository.UsedCarRepository;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.outbox.OutboxPayloadWrapper;
import com.apes.framework.plugin.outbox.annotation.OutboxSubscriber;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.MapUtil;
import com.apes.scm.income.model.MoneyIncome;
import com.apes.scm.income.model.MoneyIncomeItem;
import com.apes.scm.income.repository.MoneyIncomeRepository;
import com.apes.scm.masterdata.party.model.AccessProvider;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.masterdata.product.model.Product;
import com.apes.scm.sal.saleOrder.SaleOrder;
import com.apes.scm.sal.saleOrder.SaleOrderRepository;
import com.apes.scm.sal.saleReturn.SaleReturn;
import com.apes.scm.sal.saleReturn.SaleReturnRepository;
import com.apes.scm.voucher.model.Voucher;
import com.apes.scm.voucher.model.VoucherFinExtension;
import com.apes.scm.voucher.model.VoucherItem;
import com.apes.scm.voucher.repository.VoucherFinExtensionRepository;
import com.apes.scm.voucher.repository.VoucherRepository;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * 功能：
 *
 * @author zhuyh
 * @time 14:25
 * @date 2020/3/3
 */
@Service("partnerCheckService")
public class PartnerCheckService extends DomainService {

    @Autowired
    private PartnerCheckRepository partnerCheckRepository;
    @Autowired
    private VoucherRepository voucherRepository;
    @Autowired
    private RetailOrderRepository retailOrderRepository;
    @Autowired
    private AdvancePaymentRepository advancePaymentRepository;
    @Autowired
    private PolicyInformationRepository policyInformationRepository;
    @Autowired
    private UsedCarRepository usedCarRepository;
    @Autowired
    private MoneyIncomeRepository moneyIncomeRepository;
    @Autowired
    private PartyRoleRepository partyRoleRepository;

    /**
     * 新增
     * @param request
     * @return
     */
    public PartnerCheck create(SimpleRequest request){
        PartnerCheck partnerCheck = request.getO(PartnerCheck.class);
        partnerCheck.setState("create");
        partnerCheck.setCreator(this.getPersonId(request));

        // 同一个公司相同起止时间只允许有一份有效的政策
        List<PartnerCheck> partnerChecks = partnerCheckRepository.findAll(JpaDsl.toCriteriaByEq(
                "fnCustomer.id", partnerCheck.getFnCustomer().getId(), "state", "approve"));
        //判断选择的起止时间是否存在
        Boolean start = checkPartnerCheckDate(partnerChecks, partnerCheck.getStartDate());
        Boolean end = checkPartnerCheckDate(partnerChecks, partnerCheck.getEndDate());

        if (start || end){
            throw new RuntimeException("保存失败，已存在有效的赋能政策，请确认!");
        }

        Calendar calendar = Calendar.getInstance(); //创建Calendar 的实例
        calendar.setTime(partnerCheck.getStartDate());
        calendar.add(Calendar.DAY_OF_MONTH,-1); //当前时间减去一天，即一天前的时间
        calendar.getTime();//返回当前时间的毫秒数
        partnerCheck.setLastCheckDate(calendar.getTime());
        Set<PartnerCheckItem> lascheck = partnerCheck.lastDateUp();
        partnerCheck.setPartnerCheckItems(lascheck);
        return partnerCheckRepository.saveAndFlush(partnerCheck);
    }

    /**
     * 检查时间是否在政策期起止起止内
     * @param partnerChecks
     * @param reconcileDate
     */
    private Boolean checkPartnerCheckDate(List<PartnerCheck> partnerChecks,Date reconcileDate){
        AtomicBoolean flag = new AtomicBoolean(false);
        if (!CollectionUtils.isEmpty(partnerChecks)){
            try {
                partnerChecks.forEach(item -> {
                    boolean belongCalendar = DateUtil.belongCalendar(reconcileDate,
                            DateUtil.dateToDate(item.getStartDate(), DateUtil.SHOW_DATE_FORMAT),
                            DateUtil.dateToDate(item.getEndDate(), DateUtil.SHOW_DATE_FORMAT));
                    if (belongCalendar){
                        flag.set(true);
                        throw new RuntimeException("终止forEach循环,减少无意义比较");
                    }
                });
            }catch (Exception e){}
        }
        return flag.get();
    }

    /**
     * 修改
     * @param request
     * @return
     */
    public PartnerCheck update(SimpleRequest request) throws Exception {
        PartnerCheck partnerCheck = request.getO(PartnerCheck.class);

        // 同一个公司相同起止时间只允许有一份有效的政策
        List<PartnerCheck> partnerChecks = partnerCheckRepository.findAll(JpaDsl.toCriteriaIgnoreNull(
                "id", "NE", partnerCheck.getId(), "fnCustomer.id","EQ", partnerCheck.getFnCustomer().getId(), "state","EQ","approve"));
        //判断选择的起止时间是否存在
        Boolean start = checkPartnerCheckDate(partnerChecks, partnerCheck.getStartDate());
        Boolean end = checkPartnerCheckDate(partnerChecks, partnerCheck.getEndDate());

        if (start || end){
            throw new RuntimeException("保存失败，已存在有效的赋能政策，请确认!");
        }

        partnerCheck.setState("create");
        partnerCheck = partnerCheckRepository.saveAndFlush(partnerCheck);
        return partnerCheck;
    }

    /**
     * 审核
     *
     * @param request
     * @return
     */
    public PartnerCheck approve(SimpleRequest request) {
        PartnerCheck partnerCheck = request.getO(PartnerCheck.class);
        partnerCheck.setState("approve");
        partnerCheck.setApproveDate(new Date());
        partnerCheck.setApproveUid(this.getPerson(request));
        partnerCheck = partnerCheckRepository.saveAndFlush(partnerCheck);
        return partnerCheck;
    }

    /**
     * 延期
     * @param request
     * @return
     */
    public PartnerCheck extension(SimpleRequest request){
        PartnerCheck partnerCheck = request.getO(PartnerCheck.class);
        partnerCheck.setState("extension");
        partnerCheck.setExtensionUid(this.getPerson(request));
        partnerCheck.setExtensionDate(new Date());
        if (partnerCheck.getStartDate().after(partnerCheck.getEndDate()) || partnerCheck.getStartDate().equals(partnerCheck.getEndDate())) {
            throw new RuntimeException("有效期止日期应大于有效期起日期");
        }

        // 同一个公司相同起止时间只允许有一份有效的政策
        List<PartnerCheck> partnerChecks = partnerCheckRepository.findAll(JpaDsl.toCriteriaIgnoreNull(
                "id", "NE", partnerCheck.getId(), "fnCustomer.id","EQ", partnerCheck.getFnCustomer().getId(), "state","EQ","approve"));
        //判断选择的起止时间是否存在
        Boolean start = checkPartnerCheckDate(partnerChecks, partnerCheck.getStartDate());
        Boolean end = checkPartnerCheckDate(partnerChecks, partnerCheck.getEndDate());

        if (start || end){
            throw new RuntimeException("保存失败，已存在有效的赋能政策，请确认!");
        }
        return partnerCheckRepository.saveAndFlush(partnerCheck);
    }

    /**
     * 终止
     *
     * @param request
     * @return
     */
    public PartnerCheck repeal(SimpleRequest request) {
        PartnerCheck partnerCheck = request.getO(PartnerCheck.class);
        partnerCheck.setState("repeal");
        partnerCheck.setRepealDate(new Date());
        partnerCheck.setRepealUid(this.getPerson(request));
        partnerCheck = partnerCheckRepository.saveAndFlush(partnerCheck);
        return partnerCheck;
    }


    /**
     * 删除
     *
     * @param request
     * @return
     */
    public String delete(SimpleRequest request) {
        PartnerCheck partnerCheck = request.getO(PartnerCheck.class);
        partnerCheck.setState("delete");
        partnerCheck.setDeleteDate(new Date());
        partnerCheck.setDeleteUid(getPerson(request));
        partnerCheckRepository.save(partnerCheck);
        return "删除成功";
    }

    /**
     * 根据合同id获取赋能商户政策
     * @param request
     * @return
     */
    public PartnerCheck queryByContractId(SimpleRequest request){
        String contractId = request.getJO().getString("id");
        List<PartnerCheck> partnerChecks = partnerCheckRepository.findAll(JpaDsl.toCriteriaByEq("fnContract.id", contractId));
        if (CollectionUtils.isEmpty(partnerChecks)){
            return null;
        }
        return partnerChecks.get(0);
    }


    //获取审核后的赋能结算合同
    public List<PartnerCheck> findByFnCustomerSh(SimpleRequest request){
        List<PartnerCheck> list= null;
        list= partnerCheckRepository.findAll(JpaDsl.toCriteriaByEq("fnCustomer.id", request.get("fnCustomer"),"state","approve"));
        if(list.size()==0){
            throw new RuntimeException("获取赋能决策失败，请先定义赋能商户决策！");
        }
        return list;
    }

    /***
     * 监听凭证的生成并计算对应的平台管理费和供应链管理费
     */
    @OutboxSubscriber(id="fn.partnerCheck.calculateVoucherFee", name="计算凭证管理费")
    public void calculateVoucherFeeSubscribe(OutboxPayloadWrapper wrapper){
        JSONObject param = JSONObject.parseObject(wrapper.getPayload());
        SimpleRequest request = new SimpleRequest();
        request.setData(param);
        Voucher voucher = calculateVoucherFee(request);
        Voucher newestVoucher = SpringManager.getBean(MerchantSettlementService.class).calculateCost(voucher);
        //构造凭证财务拓展表
        buildVoucherFinExtension(newestVoucher);
    }

    public Voucher calculateVoucherFee(SimpleRequest request) {
        Voucher voucher = voucherRepository.findOne((String)request.get("id"));
        if (!voucher.getVoucherType().equals("CUSTOMER_SALE")) return voucher;  // 只处理销售凭证

        // 业务单据类型： 零售订单、分销订单、分销退货、零售退货, 耗材领用
        // 凭证类型为 CUSTOMER_SALE
        List<String> conditionArray = Arrays.asList("RetailOrder","SaleOrder", "SaleReturn", "RetailReturn", "ConsumableUse");

        if ((voucher.getBusinessType() != null && conditionArray.contains(voucher.getBusinessType()))){
            PartnerCheckCreate partnerCheckCreate = new PartnerCheckCreate();

            // 计算平台服务费
            if(!isEqualAccessProvider(voucher)){
                partnerCheckCreate.getPlatformManagementFee(voucher);
                partnerCheckCreate.getPlatformServiceFeeReduced(voucher);
                //平台管理费-定损基地
                partnerCheckCreate.getBasePlatformServiceFee(voucher, PartnerCheckCreate.Type.BasePlatform);
                //平台管理费-定损基地（减免）
                partnerCheckCreate.getBasePlatformServiceFee(voucher, PartnerCheckCreate.Type.PlatformReduced);
            }else {
                //计算内部销售减免金额
                partnerCheckCreate.getPlatformInternalReduced(voucher);
            }

            // 计算供应链管理费
            partnerCheckCreate.getSupplyChainManagementFee(voucher);

            // 处理客户扩展表
            getFnCustomerExpand(voucher);

            /** 统计合计 **/
            double platformManagementFee = voucher.getVoucherItems().stream().mapToDouble(VoucherItem::getPlatformManagementFee).sum();
            voucher.setPlatformManagementFee(platformManagementFee);    // 平台管理费

            double supplyChainManagementFee = voucher.getVoucherItems().stream().mapToDouble(VoucherItem::getSupplyChainManagementFee).sum();
            voucher.setSupplyChainManagementFee(supplyChainManagementFee);    // 供应链管理费

            double platformServiceFeeReduced = voucher.getVoucherItems().stream().mapToDouble(VoucherItem::getPlatformServiceFeeReduced).sum();
            voucher.setPlatformServiceFeeReduced(platformServiceFeeReduced);    // 平台服务费减免额

            voucher = voucherRepository.save(voucher);
        }
        return voucher;
    }

    /**
     * 公司与客户同同一接入商不计算平台服务费（排除零售自己卖给自己客户的情况）
     * @param voucher CustomerSaleVoucher
     * @return boolean
     */
    private boolean isEqualAccessProvider(Voucher voucher) {
        // 存在零售单凭证客户挂自己的情况,直接卖给客户，这部分需要计算
        if (voucher.getPartner().getParty().getId() == voucher.getCompany().getParty().getId()) {
            return false;
        }

        // 同一接入商
        AccessProvider companyAccess = voucher.getCompany().queryAccessProvider();
        PartyRole partnerCompany = partyRoleRepository.findByPartyIdAndRoleId(voucher.getPartner().getParty().getId(), "Company");
        if (partnerCompany != null && companyAccess.getId().equals(partnerCompany.queryAccessProvider().getId())){
            return true;
        }
        return false;
    }

    /**
     * 获取对应的扩展表信息
     * @param voucher CustomerSaleVoucher
     */
    private void getFnCustomerExpand(Voucher voucher) {

        if (voucher.getCustomerExpand() != null) return;

        String customerExpand = null;
        if (voucher.getOriginBusinessType().equals("RetailOrder")){
            RetailOrder retailOrder = SpringManager.getBean(RetailOrderRepository.class).findOne(voucher.getOrigin());
            if (retailOrder != null && retailOrder.getCustomerExpand() != null) customerExpand = retailOrder.getCustomerExpand().getId();
        } else if(voucher.getOriginBusinessType().equals("SaleOrder")){
            SaleOrder saleOrder = SpringManager.getBean(SaleOrderRepository.class).findOne(voucher.getOrigin());
            if (saleOrder != null) customerExpand = saleOrder.getFnCustomerExpandId();
        } else if(voucher.getOriginBusinessType().equals("SaleReturn")){
            SaleReturn saleReturn = SpringManager.getBean(SaleReturnRepository.class).findOne(voucher.getOrigin());
            if (saleReturn != null && saleReturn.getSaleOrder() != null) customerExpand = saleReturn.getSaleOrder().getFnCustomerExpandId();
        }else if(voucher.getOriginBusinessType().equals("RetailReturn")){
            RetailReturn retailReturn = SpringManager.getBean(RetailReturnRepository.class).findOne(voucher.getOrigin());
            if (retailReturn != null && retailReturn.getCustomerExpand() != null) customerExpand = retailReturn.getCustomerExpand().getId();
        }

        voucher.setCustomerExpand(customerExpand != null ? customerExpand : null);
    }


//    /***
//     * 监听零售单审核
//     */
//    @OutboxSubscriber(id="fn.partnerCheck.calculateRetailFee", name="计算零售订单平台管理费")
//    public void calculateRetailFeeSubscribe(OutboxPayloadWrapper wrapper){
//        JSONObject param = JSONObject.parseObject(wrapper.getPayload());
//        SimpleRequest request = new SimpleRequest();
//        request.setData(param);
//        calculateRetailFee(request);
//    }

    /**
     *
     * 实现方式: 通过业务事件订阅
     *
     * 储值/年卡售卖
     * 储值/定金 年卡使用
     *
     */
    public void calculateRetailFee(SimpleRequest request) {
        String id = request.get("id");
        RetailOrder retailOrder = retailOrderRepository.findOne(id);
        PartnerCheckCreate partnerCheckCreate = new PartnerCheckCreate();
        calculateSale(retailOrder, partnerCheckCreate);
        calculateUse(retailOrder, partnerCheckCreate);
        calculateTmallFee(retailOrder, partnerCheckCreate);
        calculateCxyPlatformFee(retailOrder, partnerCheckCreate);
        retailOrderRepository.save(retailOrder);
    }

    /***
     * 用于缓存商品的服务类型
     */

    private Map<String,String> cached = new HashMap<>();

    private String cachedServiceType(Product product) {
        if (!PartnerCheckCreate.isCached) return product.queryServeType().getId();

        String serviceTypeId = cached.get(product.getId());
       if (serviceTypeId != null) return serviceTypeId;

        serviceTypeId = product.queryServeType().getId();
        cached.put(product.getId(), serviceTypeId);
        return serviceTypeId;
    }


    /***
     * 计算售卖
     */
    private void calculateSale(RetailOrder retailOrder, PartnerCheckCreate partnerCheckCreate) {
        List<Map> items = retailOrder.getSaleItems().stream()
                // 判断是否为储值年卡售卖
                .filter(saleItem -> cachedServiceType(saleItem.getProduct()).equals("012") ||   // 会员储值
                        cachedServiceType(saleItem.getProduct()).equals("010"))                 // 年卡
                .map(saleItem -> MapUtil.mapper(
                        "item", saleItem,
                        "product", saleItem.getProduct(),
                        "classifyId", saleItem.getProduct().getClassify().getId(),
                        "companyId", saleItem.getOrder().getCompany().getId(),
                        "cost", saleItem.getPriceTotal()
                )).collect(Collectors.toList());

        if (items.size() == 0) return;

        partnerCheckCreate.getFee(items, PartnerCheckCreate.Type.Platform);

        items.forEach( item ->{
            RetailOrderItem retailOrderItem = (RetailOrderItem) item.get("item");
            retailOrderItem.setPlatformManagementFee(item.get("platformManagementFee") != null ? ((double) item.get("platformManagementFee")) : 0.0);
        });
    }

    /***
     * 计算使用
     */
    private void calculateUse(RetailOrder retailOrder, PartnerCheckCreate partnerCheckCreate) {

        List<Map> items = retailOrder.getPaymentMethodSet().stream()
                // 判断是否为储值定金年卡兑换券置换使用
                .map(payMethod -> {
                    if (payMethod.getPaymentMethodType().getPaymentType().getCode().equals("collectInAdvance")) {
                        return MapUtil.mapper(
                                "item", payMethod,
                                "classifyId", null,
                                "companyId", payMethod.getOrder().getCompany().getId(),
                                "cost", -1 * payMethod.getAmount()
                        );
                    }else {
                        return MapUtil.mapper(
                                "item", payMethod,
                                "classifyId", null,
                                "companyId", payMethod.getOrder().getCompany().getId(),
                                "cost", 1 * payMethod.getAmount()
                        );
                    }
                }).collect(Collectors.toList());
        if (items.size() == 0) return;

        partnerCheckCreate.getFee(items, PartnerCheckCreate.Type.Platform);

        items.forEach( item ->{
            RetailOrderPayMethod retailOrderPayMethod = (RetailOrderPayMethod) item.get("item");
            retailOrderPayMethod.setPlatformManagementFee(item.get("platformManagementFee") != null ?  ((double) item.get("platformManagementFee")) : 0.0);
        });
        retailOrder.setCalculateFlag(true);
    }
    /***
     * 计算天猫平台费用
     */
    private void calculateTmallFee(RetailOrder retailOrder, PartnerCheckCreate partnerCheckCreate) {
        if (Objects.isNull(retailOrder.getChannel()))return;
        if (Objects.nonNull(retailOrder.getChannel())&&!"100".equals(retailOrder.getChannel().getId())) return;
        List<Map> items = retailOrder.getPaymentMethodSet().stream()
                .map(payMethod -> MapUtil.mapper(
                        "item", payMethod,
                        "classifyId", null,
                        "companyId", payMethod.getOrder().getCompany().getId(),
                        "cost", 1 * payMethod.getAmount()
                )).collect(Collectors.toList());

        if (items.size() == 0) return;

        partnerCheckCreate.getFee(items, PartnerCheckCreate.Type.T_MALL);

        items.forEach( item ->{
            RetailOrderPayMethod retailOrderPayMethod = (RetailOrderPayMethod) item.get("item");
            retailOrderPayMethod.setDrainagePlatformFee(item.get("platformManagementFee") != null ?  ((double) item.get("platformManagementFee")) : 0.0);
        });
    }

    /***
     * 计算车行易平台佣金
     */
    private void calculateCxyPlatformFee(RetailOrder retailOrder, PartnerCheckCreate partnerCheckCreate) {
        if (Objects.isNull(retailOrder.getChannel()))return;
        if (!"75".equals(retailOrder.getChannel().getId())) return;
        List<Map> items = retailOrder.getPaymentMethodSet().stream()
                .map(payMethod -> MapUtil.mapper(
                        "item", payMethod,
                        "classifyId", null,
                        "companyId", payMethod.getOrder().getCompany().getId(),
                        "cost", 1 * payMethod.getAmount()
                )).collect(Collectors.toList());

        if (items.size() == 0) return;

        partnerCheckCreate.getFee(items, PartnerCheckCreate.Type.CXY);

        items.forEach( item ->{
            RetailOrderPayMethod retailOrderPayMethod = (RetailOrderPayMethod) item.get("item");
            retailOrderPayMethod.setDrainagePlatformFee(item.get("platformManagementFee") != null ?  ((double) item.get("platformManagementFee")) : 0.0);
        });
    }



    /***
     * 监听订金单
     */
    @OutboxSubscriber(id="fn.partnerCheck.calculateAdvancePaymentFee", name="计算订金单平台管理费")
    public void calculateAdvancePaymentFeeSubscribe(OutboxPayloadWrapper wrapper){
        JSONObject param = JSONObject.parseObject(wrapper.getPayload());
        SimpleRequest request = new SimpleRequest();
        request.setData(param);
        calculateAdvancePaymentFee(request);
    }

    @Autowired
    private MongoTemplate mongoTemplate;

    public void calculateAdvancePaymentFee(SimpleRequest request) {
        AdvancePayment advancePayment = advancePaymentRepository.findOne((String) request.get("id"));

        PartnerCheckCreate partnerCheckCreate = new PartnerCheckCreate();
        List<Map> paymentMethods = advancePayment.getPaymentMethodSet().stream()
//                .filter(paymentItem -> paymentItem.getProduct().queryServeType().getId().equals("012"))     // 012 会员储值
                .map(paymentMethod -> MapUtil.mapper(
                        "paymentMethod", paymentMethod,
                        "classifyId", null,
                        "companyId", paymentMethod.getPayment().getCompany().getId(),
                        "cost", paymentMethod.getAmount()
                )).collect(Collectors.toList());

        if (paymentMethods.size() == 0) return;

        partnerCheckCreate.getFee(paymentMethods, PartnerCheckCreate.Type.Platform);

        // 记录 MongoDB 日志
        Document document = new Document();
        document.put("orderId", advancePayment.getId());
        document.put("paymentMethods", paymentMethods.toString());
        mongoTemplate.getCollection("AdvancePaymentFee").insertOne(document);

        paymentMethods.forEach( method ->{
            AdvancePaymentMethod advancePaymentMethod = (AdvancePaymentMethod) method.get("paymentMethod");
            advancePaymentMethod.setPlatformManagementFee(method.get("platformManagementFee") != null ?  ((double) method.get("platformManagementFee")) : 0.0);
        });
        advancePayment.setCalculateFlag(true);
        advancePaymentRepository.saveAndFlush(advancePayment);
    }


    /***
     * 监听保单信息
     */
    @OutboxSubscriber(id="fn.partnerCheck.calculatePolicyInformationFee", name="计算保单信息佣金")
    public void calculatePolicyInformationFeeSubscribe(OutboxPayloadWrapper wrapper){
        JSONObject param = JSONObject.parseObject(wrapper.getPayload());
        SimpleRequest request = new SimpleRequest();
        request.setData(param);
        calculatePolicyInformationFee(request);
    }

    public void calculatePolicyInformationFee(SimpleRequest request) {
        PolicyInformation policyInformation = policyInformationRepository.findOne((String) request.get("id"));

        PartnerCheckCreate partnerCheckCreate = new PartnerCheckCreate();

        List<Map> items = policyInformation.getPolicyInformationItems().stream()
                .map(policyInformationItem -> MapUtil.mapper(
                        "item", policyInformationItem,
                        "classifyId", null,
                        "companyId", policyInformationItem.getPolicyInformation().getCompany().getId(),
                        "cost", policyInformationItem.getFnCommission()
                )).collect(Collectors.toList());

        if (items.size() == 0) return;

        partnerCheckCreate.getFee(items, PartnerCheckCreate.Type.Platform);

        items.forEach( item ->{
            PolicyInformationItem policyInformationItem = (PolicyInformationItem) item.get("item");
            policyInformationItem.setPlatformManagementFee(item.get("platformManagementFee") != null ?  ((double) item.get("platformManagementFee")) : 0.0);
        });

        policyInformationRepository.save(policyInformation);
    }


    /***
     * 监听二手车
     */
    @OutboxSubscriber(id="fn.partnerCheck.calculateUsedCarFee", name="计算二手车服务费")
    public void calculateUsedCarFeeSubscribe(OutboxPayloadWrapper wrapper){
        JSONObject param = JSONObject.parseObject(wrapper.getPayload());
        SimpleRequest request = new SimpleRequest();
        request.setData(param);
        calculateUsedCarFee(request);
    }

    public void calculateUsedCarFee(SimpleRequest request) {
        UsedCar usedCar = usedCarRepository.findOne((String) request.get("id"));

        PartnerCheckCreate partnerCheckCreate = new PartnerCheckCreate();
        List<Map> items = new ArrayList();
        items.add(MapUtil.mapper(
                "cost", usedCar.getStorePrice(),
                "classifyId", null,
                "companyId", usedCar.getCompany().getId()
        ));

        partnerCheckCreate.getFee(items, PartnerCheckCreate.Type.UsedCar);

        items.forEach( item -> {
            usedCar.setPlatformManagementFee( item.get("platformManagementFee") != null ?  ((double) item.get("platformManagementFee")) : 0.0);
        });
        usedCar.setCalculateFlag(true);
        usedCarRepository.saveAndFlush(usedCar);
    }


    /***
     * 监听资金收入单
     */
    @OutboxSubscriber(id="fn.partnerCheck.calculateMoneyIncomeFee", name="计算二手车服务费")
    public void calculateMoneyIncomeFeeSubscribe(OutboxPayloadWrapper wrapper){
        JSONObject param = JSONObject.parseObject(wrapper.getPayload());
        SimpleRequest request = new SimpleRequest();
        request.setData(param);
        calculateMoneyIncomeFee(request);
    }

    /**
     * 计算资金收入平台服务费
     * @param request {"id":""}
     */
    public void calculateMoneyIncomeFee(SimpleRequest request) {
        MoneyIncome moneyIncome = moneyIncomeRepository.findOne((String) request.get("id"));
        PartnerCheckCreate partnerCheckCreate = new PartnerCheckCreate();
        List<Map> items = moneyIncome.getMoneyIncomeItems()
                .stream().map(moneyIncomeItem -> MapUtil.mapper(
                        "item", moneyIncomeItem,
                        "classifyId", null,
                        "companyId", moneyIncome.getCompany().getId(),
                        "cost", moneyIncomeItem.getIncomeAmount()
                )).collect(Collectors.toList());

        partnerCheckCreate.getFee(items, PartnerCheckCreate.Type.Platform);

        items.forEach(item -> {
            MoneyIncomeItem moneyIncomeItem = (MoneyIncomeItem) item.get("item");
            moneyIncomeItem.setPlatformManagementFee(item.get("platformManagementFee") != null ? ((double) item.get("platformManagementFee")) : 0.0);
        });

        moneyIncome.setCalculateFlag(true);
        moneyIncomeRepository.saveAndFlush(moneyIncome);
    }

    public void buildVoucherFinExtension(Voucher voucher){
        VoucherFinExtension voucherFinExtension = new VoucherFinExtension();
        voucherFinExtension.setVoucher(voucher);
        voucherFinExtension.setId(voucher.getId());
        voucherFinExtension.setCompany(voucher.getCompany());
        voucherFinExtension.setPlatformCompany(voucher.getPlatformCompany());
        voucherFinExtension.setDept(voucher.getDept());
        voucherFinExtension.setVoucherType(voucher.getVoucherType());
        voucherFinExtension.setClassification(voucher.getClassification());
        voucherFinExtension.setInventoryMode(voucher.getInventoryMode());
        voucherFinExtension.setSupplyChainManagementFee(voucher.getSupplyChainManagementFee());     //供应链管理费
        voucherFinExtension.setPlatformManagementFee(voucher.getPlatformManagementFee());         //平台管理费
        voucherFinExtension.setPlatformServiceFeeReduced(voucher.getPlatformServiceFeeReduced());   //平台服务费减免额
        voucherFinExtension.setLossQuotationFee(voucher.getVoucherItems().stream().mapToDouble(VoucherItem::getLossQuotationFee).sum()); //定损信息费合计
        voucherFinExtension.setPlatformInternalReduced(voucher.getVoucherItems().stream().mapToDouble(VoucherItem::getPlatformInternalReduced).sum());  //内部销售服务费减免额度
        voucherFinExtension.setBasePlatformManagementFee(voucher.getVoucherItems().stream().mapToDouble(VoucherItem::getBasePlatformManagementFee).sum()); //定损基地平台服务费

        SpringManager.getBean(VoucherFinExtensionRepository.class).saveAndFlush(voucherFinExtension);
    }

}
